package org.jeecg.modules.manage.technology.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.ChatMemoryProvider;
import dev.langchain4j.model.chat.ChatModel;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.modules.analysis.genealogy.entity.Genealogy;
import org.jeecg.modules.analysis.genealogy.service.IGenealogyService;
import org.jeecg.modules.demo.patent.entity.Patent;
import org.jeecg.modules.demo.patent.service.IPatentService;
import org.jeecg.modules.manage.technology.entity.PatentGenealogy;
import org.jeecg.modules.manage.technology.mapper.PatentGenealogyMapper;
import org.jeecg.modules.manage.technology.service.ITechnologyService;
import org.jeecg.modules.manage.technology.service.ai.AiAssistant;
import org.jeecg.modules.manage.technology.service.ai.record.PatentTechnologyAnalysis;
import org.jeecg.modules.manage.technology.util.FileDownloadUtil;
import org.jeecg.modules.manage.technology.util.PdfParseUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 技术识别服务实现类
 * @Author: jeecg-boot
 * @Date: 2025-11-03
 * @Version: V1.0
 */
@Slf4j
@Service
public class TechnologyServiceImpl extends ServiceImpl<PatentGenealogyMapper, PatentGenealogy> implements ITechnologyService {

    @Autowired
    private IGenealogyService genealogyService;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private FileDownloadUtil fileDownloadUtil;

    @Autowired
    private PdfParseUtil pdfParseUtil;

    @Autowired
    private AiAssistant aiAssistant;

    @Autowired
    private IPatentService patentService;

    @Autowired
    private ChatMemory chatMemory;

    @Override
    public int batchAnalyzePatentTechnology(List<Patent> patentList) {
        if (CollUtil.isEmpty(patentList)) {
            return 0;
        }

        int successCount = 0;
        int totalCount = patentList.size();

        log.info("开始批量处理专利，总数：{}", totalCount);

        for (int i = 0; i < totalCount; i++) {
            Patent patent = patentList.get(i);

            try {
                log.info("正在处理第{}/{}个专利：{}", i + 1, totalCount, patent.getOriginName());
                analyzeAndSavePatentTechnology(patent);
                successCount++;

                // 避免频繁调用API，每次间隔1秒
                if (i < totalCount - 1) {
                    ThreadUtil.sleep(1000);
                }
            } catch (Exception e) {
                log.error("处理专利[{}]失败：{}", patent.getOriginName(), e.getMessage());
            }
        }

        log.info("批量处理完成，成功{}/{}个专利", successCount, totalCount);
        return successCount;
    }


    @Override
    public List<String> analyzeAndSavePatentTechnology(Patent patent) {
        if (patent == null || StrUtil.isEmpty(patent.getId())) {
            log.error("专利信息为空或缺少ID");
            return new ArrayList<>();
        }

        try {
            // 1. 检查AI助手服务是否可用
            if (aiAssistant == null) {
                log.error("AiAssistant未初始化，请检查LangChain4j配置");
                throw new RuntimeException("AI助手服务未配置或未启用");
            }

            // 2. 获取所有技术谱系
            List<Genealogy> genealogyList = genealogyService.getAllGenealogyList();

            // 3. 使用AI助手分析专利技术和政府资助信息
            log.info("开始AI分析，专利：{}", patent.getOriginName());
            PatentTechnologyAnalysis analysis = analyzePatentWithAi(patent, genealogyList);


            // 4. 向上遍历技术谱系，添加所有父级节点
            List<String> genealogyIdList = addAllParentGenealogyIds(analysis.genealogyIds(), genealogyList);
            log.info("包含父级节点后，最终技术ID数量：{}", genealogyIdList.size());

            // 5. 使用事务保护更新专利信息和保存技术谱系关联关系
            transactionTemplate.executeWithoutResult(status -> {
                try {
                    // 5.更新专利信息（政府资助和AI处理状态）
                    updatePatent(patent, analysis);

                    // 6. 保存技术谱系关联关系
                    savePatentGenealogyRelations(genealogyIdList, patent);
                } catch (Exception e) {
                    log.error("事务处理失败：{}", e.getMessage(), e);
                    status.setRollbackOnly();
                    throw new RuntimeException("保存专利分析结果失败", e);
                }
            });


            String technologyNames = genealogyIdList.stream()
            .map(id -> genealogyList.stream()
                        .filter(g -> id.equals(g.getId()))
                        .findFirst()
                        .map(Genealogy::getName)
                        .orElse("未知(ID:" + id + ")")
                )
            .collect(Collectors.joining(" | "));  // 直接连接，不用中间List
            log.info("专利[{}]识别到{}个技术分类：{}", patent.getOriginName(), genealogyIdList.size(), technologyNames);

            return genealogyIdList;
        } catch (Exception e) {
            log.error("分析专利技术失败：{}", e.getMessage(), e);
            throw new RuntimeException("分析专利技术失败：" + e.getMessage());
        }
    }



    /**
     * 保存专利技术谱系关联关系（批量插入）
     * 注意：此方法依赖外层事务管理
     */
    public void savePatentGenealogyRelations(List<String> genealogyIdList, Patent patent) {
        // 1. 删除旧关联
        QueryWrapper<PatentGenealogy> deleteWrapper = new QueryWrapper<>();
        deleteWrapper.eq("patent_id", patent.getId());
        baseMapper.delete(deleteWrapper);

        // 2. 批量插入新关联
        if (CollUtil.isNotEmpty(genealogyIdList)) {
            Date now = new Date();

            for (String genealogyId : genealogyIdList) {
                PatentGenealogy relation = new PatentGenealogy();
                relation.setPatentId(patent.getId());
                relation.setGenealogyId(genealogyId);
                relation.setCreateBy("system");
                relation.setCreateTime(now);

                // 使用 baseMapper 插入
                baseMapper.insert(relation);
            }

            log.info("专利[{}]批量保存了{}个技术分类关联", patent.getOriginName(), genealogyIdList.size());
        }
    }



    /**
     * 使用AI助手分析专利技术和政府资助（支持PDF文件解析）
     *
     * @param patent        专利对象
     * @param genealogyList 技术谱系列表
     * @return AI分析结果（包含技术和政府资助信息）
     */
    private PatentTechnologyAnalysis analyzePatentWithAi(Patent patent, List<Genealogy> genealogyList) {
        // 构建专利内容（包含基本信息和PDF内容）
        StringBuilder patentContent = new StringBuilder();

        // 添加专利基本信息
        patentContent.append("专利名称：").append(patent.getOriginName()).append("\n");
        if (StrUtil.isNotEmpty(patent.getApplyId())) {
            patentContent.append("申请号：").append(patent.getApplyId()).append("\n");
        }

        // 处理PDF文件内容
        String fileUrl = patent.getFileString();
        if (StrUtil.isNotEmpty(fileUrl) && pdfParseUtil.isPdfFile(fileUrl)) {
            log.info("发现PDF文件，开始下载和解析：{}", fileUrl);

            byte[] pdfBytes = fileDownloadUtil.downloadFile(fileUrl);
            if (pdfBytes != null && pdfBytes.length > 0) {
                String extractedContent = pdfParseUtil.parsePdfContent(pdfBytes);
                if (StrUtil.isNotEmpty(extractedContent)) {
                    patentContent.append("\n专利详细内容：\n").append(extractedContent);
                    log.info("已提取PDF文本内容({} 字符)", extractedContent.length());
                }
            }
        }

        // 构建技术谱系选项
        StringBuilder genealogyOptions = new StringBuilder();
        for (Genealogy genealogy : genealogyList) {
            genealogyOptions.append("ID: ").append(genealogy.getId()).append(" - ").append(genealogy.getName()).append("\n");
        }

        // 使用结构化输出同时进行技术分析和美国政府资助判断
        PatentTechnologyAnalysis analysis = aiAssistant.analyzePatentTechnologyStructured(patentContent.toString(), genealogyOptions.toString());
        

        // 直接返回AI分析结果
        return analysis != null ? analysis : PatentTechnologyAnalysis.empty("分析失败");
    }

    /**
     * 向上遍历技术谱系，添加所有父级节点（不包含顶级节点）
     * 对于每个技术ID，将其所有父级节点也添加到结果中
     *
     * @param originalIds   原始AI分析得到的技术ID列表
     * @param genealogyList 所有技术谱系数据
     * @return 包含所有父级节点的技术ID列表
     */
    private List<String> addAllParentGenealogyIds(List<String> originalIds, List<Genealogy> genealogyList) {
        if (CollUtil.isEmpty(originalIds) || CollUtil.isEmpty(genealogyList)) {
            return originalIds;
        }

        // 构建 ID -> Genealogy 的映射，方便快速查找
        Map<String, Genealogy> genealogyMap = genealogyList.stream()
                .collect(Collectors.toMap(Genealogy::getId, g -> g, (existing, replacement) -> existing));

        // 使用 Set 去重，保证每个ID只出现一次
        Set<String> resultSet = new LinkedHashSet<>(originalIds);

        // 对每个原始ID，向上遍历所有父级节点
        for (String currentId : originalIds) {
            addParentIdsRecursively(currentId, genealogyMap, resultSet);
        }

        List<String> result = new ArrayList<>(resultSet);
        if (result.size() > originalIds.size()) {
            log.info("向上遍历成功：从{}个原始技术扩展到{}个（包含父级）",originalIds.size(), result.size());
        }

        return result;
    }

    /**
     * 递归添加父级ID（排除顶级节点pid=0）
     *
     * @param currentId     当前ID
     * @param genealogyMap  技术谱系映射
     * @param resultSet     结果集合
     */
    private void addParentIdsRecursively(String currentId, Map<String, Genealogy> genealogyMap, Set<String> resultSet) {
        if (StrUtil.isEmpty(currentId) || !genealogyMap.containsKey(currentId)) {
            return;
        }

        Genealogy current = genealogyMap.get(currentId);
        String parentId = current.getPid();

        // 如果有父级ID且不是顶级节点（pid != "0"）且未被处理过
        if (StrUtil.isNotEmpty(parentId) && !"0".equals(parentId) && genealogyMap.containsKey(parentId)) {
            // 添加父级ID（Set会自动去重）
            boolean added = resultSet.add(parentId);

            if (added) {
                log.debug("添加父级技术谱系：{} -> {}", currentId, parentId);
                // 递归处理父级的父级
                addParentIdsRecursively(parentId, genealogyMap, resultSet);
            }
            // 如果已经存在，说明之前已经处理过这个分支，避免无限递归
        } else if ("0".equals(parentId)) {
            log.debug("到达顶级节点（pid=0），停止向上遍历：{}", currentId);
        }
    }

    /**
     * 根据AI分析结果更新专利信息（政府资助和AI处理状态）
     * 注意：此方法依赖外层事务管理
     *
     * @param patent 专利对象
     * @param analysis AI分析结果
     */
    private void updatePatent(Patent patent, PatentTechnologyAnalysis analysis) {
        try {
            log.info("开始更新专利信息，专利：{}", patent.getOriginName());

            if (analysis != null) {
                String isUsGovFundedStr = analysis.isUsGovFunded();
                String fundingInfo = analysis.usGovFundingInfo();

                // 转换为Integer类型，直接使用AI的判断结果
                Integer isUsGovFunded = ("1".equals(isUsGovFundedStr)) ? 1 : 0;
                patent.setIsUsGovFunded(isUsGovFunded);
                patent.setUsGovFundingInfo(StrUtil.isNotEmpty(fundingInfo) ? fundingInfo : null);

                // 标记为已处理
                patent.setAiProcessed(1);

                // 更新数据库
                patentService.updateById(patent);

                if (isUsGovFunded == 1) {
                    log.info("检测到美国政府资助专利：{}，资助信息：{}", patent.getOriginName(), fundingInfo);
                } else {
                    log.debug("非美国政府资助专利：{}", patent.getOriginName());
                }
            } else {
                // 分析结果为空
                log.warn("分析结果为空，设置默认值");

            }

        } catch (Exception e) {
            log.error("更新专利信息失败：{}", e.getMessage(), e);

        }
    }

    // 原 buildPatentContentForUsGovAnalysis 方法不再需要（已合并到 analyzePatentWithAi 中）
}

